﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Composite.Presentation.Regions;
using Microsoft.Practices.Composite.Regions;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;

namespace MP3Ganizer.Controls.Avalon
{
    public class AvalonPaneRegionAdapter<TPane, TContent> : RegionAdapterBase<TPane>
        where TPane : AvalonDock.Pane
        where TContent : AvalonDock.ManagedContent
    {
        public delegate void TContentHandler();

        public AvalonPaneRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
            : base(regionBehaviorFactory)
        {
        }

        protected override IRegion CreateRegion()
        {
            return new Region();
        }

        protected override void Adapt(IRegion region, TPane regionTarget)
        {

            //var itemCollection = regionTarget.Items as INotifyCollectionChanged;
            //itemCollection.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
            //{
            //    OnSelectionChanged(sender, e, region, regionTarget);
            //}; 

            region.Views.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                OnViewsCollectionChanged(sender, e, region, regionTarget);
            };

            region.ActiveViews.CollectionChanged += new NotifyCollectionChangedEventHandler(OnActiveViewsCollectionChanged);
        }

        void OnActiveViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (var item in e.NewItems)
                {
                    if (item is TContent)
                        ((TContent)item).Activate();
                    else if (item is FrameworkElement)
                        ((TContent)((FrameworkElement)item).Parent).Activate();
                }
            }
        }

        //private void OnSelectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, TPane regionTarget)
        //{
        //    if (e.Action == NotifyCollectionChangedAction.Remove)
        //    {
        //        foreach (var item in e.OldItems)
        //        {
        //            TContent content = item as TContent;
        //            if (content != null)
        //            {
        //                if (region.ActiveViews.Contains(content))
        //                    region.Remove(content);
        //                else if (region.ActiveViews.Contains(content.Content))
        //                    region.Remove(content.Content);
        //            }
        //        }
        //    }
        //}

        private void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, TPane regionTarget)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    {
                        foreach (object item in e.NewItems)
                        {
                            var newContent = item as TContent;

                            if (newContent == null)
                            {
                                newContent = (TContent)Activator.CreateInstance(typeof(TContent));
                                newContent.Content = item;

                                //IDockableContent TContent = item as IDockableContent;
                                //if (TContent != null)
                                //{
                                //    newContent.Title = TContent.Title;
                                //    newContent.IsCloseable = TContent.IsCloseable;
                                //    newContent.Closing += new EventHandler<CancelEventArgs>(TContent.OnTryClosing); //TD: gerer la desinscription
                                //    newContent.GotFocus += new System.Windows.RoutedEventHandler(TContent.OnFocusChanged);
                                //}

                                var dockableContent = newContent as AvalonDock.DockableContent;
                                if (dockableContent != null)
                                    dockableContent.StateChanged += delegate(object contentSender, RoutedEventArgs eventArg)
                                    {
                                        ContentStateChanged(contentSender, region);
                                    };

                                newContent.Closed += delegate(object contentSender, EventArgs eventArg)
                                {
                                    ContentClosed(contentSender, region);
                                };
                            }
                            regionTarget.Items.Add(newContent);
                            //newContent.InvalidateParents();
                        }
                        break;
                    }
                case NotifyCollectionChangedAction.Remove:
                    {
                        foreach (object item in e.OldItems)
                        {
                            if (regionTarget.Items.Contains(item))
                                regionTarget.Items.Remove(item);
                            else if (item is FrameworkElement)
                            {
                                FrameworkElement content = (FrameworkElement)item;
                                regionTarget.Items.Remove(content.Parent);
                            }
                        }
                        break;
                    }
            }
        }

        private void ContentStateChanged(object contentSender, IRegion region)
        {
            var content = contentSender as AvalonDock.DockableContent;
            if (content != null && content.State == AvalonDock.DockableContentState.Hidden)
                RemoveContentFromRegion((TContent)contentSender, region);
        }

        private void ContentClosed(object contentSender, IRegion region)
        {
            TContent content = contentSender as TContent;
            if (content != null)
                RemoveContentFromRegion(content, region);
        }

        private void RemoveContentFromRegion(TContent content, IRegion region)
        {
            if (region.ActiveViews.Contains(content))
                region.Remove(content);
            else if (region.ActiveViews.Contains(content.Content))
                region.Remove(content.Content);
        }
    }
}
